package xyz.lwm.lazycat.jdbc.exec;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import java.util.Map;

/**
 * lightweight jdbc operations
 *
 * @author lwm
 */
public interface JdbcOperator {

    ////////////////// execute, base //////////////////

    /**
     * execute jdbc action and return result. <br>
     * open connection and close it automatically after action.
     *
     * @param action connection action
     * @param <T> return type
     * @return result
     * @throws DataAccessException if error
     */
    @Nullable <T> T execute(@NotNull JdbcCallback<Connection, T> action) throws DataAccessException;

    /**
     * execute jdbc action and return result. <br>
     * open connection and close it automatically after action.<br>
     * closed automatically.
     *
     * @param psc    prepared statement creator
     * @param action action which prepare statement
     * @param <T>    return type
     * @return result
     * @throws DataAccessException if error
     */
    @Nullable <T> T execute(@NotNull PreparedStatementCreator psc, @NotNull JdbcCallback<PreparedStatement, T> action) throws DataAccessException;

    ////////////////// query //////////////////

    /**
     * prepare statement for sql, set parameters and execute query. closed automatically.
     *
     * @param sql           query sql
     * @param pss           prepared statement setter, it sets params
     * @param resultHandler call back, result handler
     * @param <T>           return type
     * @return result
     * @throws DataAccessException when error
     */
    @Nullable <T> T query(@NotNull String sql, @Nullable PreparedStatementSetter pss, @NotNull JdbcCallback<ResultSet, T> resultHandler) throws DataAccessException;

    /**
     * query for list. closed automatically.
     *
     * @param sql       query sql
     * @param rowMapper row mapper
     * @param args      query parameters
     * @param <T>       element type
     * @return list result
     * @throws DataAccessException when error
     */
    @NotNull <T> List<T> queryList(@NotNull String sql, @NotNull RowMapper<T> rowMapper, Object... args) throws DataAccessException;

    /**
     * query for bean list. closed automatically.
     *
     * @param sql         query sql
     * @param elementType element type
     * @param args        query parameters
     * @param <T>         element type
     * @return list result
     * @throws DataAccessException when error
     */
    @NotNull <T> List<T> queryList(@NotNull String sql, @NotNull Class<T> elementType, Object... args) throws DataAccessException;

    /**
     * query for map list. closed automatically.
     *
     * @param sql  query sql
     * @param args query parameters
     * @return map list
     * @throws DataAccessException when error
     */
    @NotNull List<Map<String, Object>> queryListForMap(@NotNull String sql, Object... args) throws DataAccessException;

    /**
     * query for one bean. closed automatically.
     *
     * @param sql         query sql
     * @param elementType element type
     * @param args        query parameters
     * @param <T>         element type
     * @return one result
     * @throws DataAccessException when error
     */
    @Nullable <T> T queryOne(@NotNull String sql, Class<T> elementType, Object... args) throws DataAccessException;

    /**
     * query for one map. closed automatically.
     *
     * @param sql  query sql
     * @param args query parameters
     * @return one map
     * @throws DataAccessException when error
     */
    @Nullable Map<String, Object> queryOneForMap(@NotNull String sql, Object... args) throws DataAccessException;

    ////////////////// update //////////////////

    /**
     * update. closed automatically.
     *
     * @param sql update sql
     * @param pss prepared statement setter, set parameters
     * @return update count
     * @throws DataAccessException when error
     */
    int update(@NotNull String sql, @Nullable PreparedStatementSetter pss) throws DataAccessException;

    /**
     * update. closed automatically.
     *
     * @param sql  update sql
     * @param args arguments
     * @return update count
     * @throws DataAccessException when error
     */
    int update(@NotNull String sql, Object... args) throws DataAccessException;

}
